package de.fhffm.gaertnerei.gui;

/**
 * @author Riad Hassani & Julian Schmücker
 */
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;

import de.fhffm.gaertnerei.tabellen.Aussaat;
import de.fhffm.gaertnerei.tabellen.Bewaesserung;
import de.fhffm.gaertnerei.tabellen.Duenger;
import de.fhffm.gaertnerei.tabellen.Ernte;
import de.fhffm.gaertnerei.tabellen.Pflanze;
import de.fhffm.gaertnerei.tabellen.Wachstum;
import de.fhffm.gaertnerei.tabellenModelle.AussaatTableModel;
import de.fhffm.gaertnerei.tabellenModelle.DuengerTableModel;
import de.fhffm.gaertnerei.tabellenModelle.PflanzeTableModel;

@SuppressWarnings("serial")
public class BearbeitenTabellenFenster extends JFrame implements ActionListener {

	private JButton buttonBearbeiten = new JButton("Bearbeiten");
	private JButton buttonLoeschen = new JButton("Löschen");
	private JButton buttonAbbrechen = new JButton("Abbrechen");
	
	private JTable tabelle = new JTable();
	
	private JScrollPane scrollPane = new JScrollPane(tabelle);
	
	private JPanel panelButton = new JPanel();
	
	private List<String> ausgewaehlteZeile = new ArrayList<String>();
	private int modus = 0;
	
	private StringBuilder stringBuilder = new StringBuilder();
	
	private Object[] options = {"Ja!","Abbrechen!"};
	
	public BearbeitenTabellenFenster(int modus){

		this.modus = modus;
		tabelleAnordnen();
		bestandteileAnordnen();
		ereignissensorenAnmeldung();
		erstelleFenster();

	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		
		Object obj = e.getSource();
		/*
		 * Wenn der Button bearbeiten gedrückt wird, wird
		 * die ausgewählte Zeile gehohlt, falls beim hohlen keiner Fehler
		 * aufgetreten sind dan wird dem Modus entsprechende Bearbeitungsfenster
		 * aufgerufen!
		 */
		if(obj == buttonBearbeiten){
			
			if(doHohleAusgewaehlteZeile()){
				
				switch(modus){
				case 1:
					new PflanzeBearbeitenFenster(ausgewaehlteZeile);
					dispose();
					break;
				case 2:
					new DuengerBearbeitenFenster(ausgewaehlteZeile);
					dispose();
					break;
				case 3:
					new AussaatBearbeitenFenster(ausgewaehlteZeile);
					dispose();
					break;
				}

			} else {
				System.out.println("Fehler beim hohlen der Pflanze");
			}
		}
		
		
		/*
		 * Wird der Button löschen gedrückt dan wird als erstes eine Entsprechende Warunung ausgegeben,
		 * dass z.B. wenn man eine Pflanze löscht auch alle Aussaaten die diese Pflanz nutzen mitgelöscht werden
		 * und der User kann entscheiden ob er nun löschen will oder nicht.
		 * Jenachdem wie der User sich entschieden hat wird die Pflanze gelöscht oder nicht und am ende wird eine
		 * Bestätigung ausgegeben
		 */
		if(obj == buttonLoeschen){
			
			if(doHohleAusgewaehlteZeile()){
				switch(modus){
				
				case 1:
					warnungLoeschePflanze();
					break;
				case 2:
					warnungLoescheDuenger();
					break;
				case 3:
					warnungLoescheAussaat();
					break;
					
				}					
			
			} else{
				System.out.println("Fehler beim hohlen der Pflanze");
			}
		}
			
		if(obj == buttonAbbrechen){
			dispose();
		}
	} 
	
	private void erstelleFenster() {
		
		setSize(800,600);
		setLocationRelativeTo(null);
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setResizable(false);
		setVisible(true);
		pack();
				
	}

	private void tabelleAnordnen() {
		
		setzeTableModel();
		scrollPane.setPreferredSize(new Dimension(600,400));
		
	}

	private void bestandteileAnordnen() {
		
		GroupLayout bearbeitenTabelle = new GroupLayout(getContentPane());
		
		getContentPane().setLayout(bearbeitenTabelle);
		
		bearbeitenTabelle.setAutoCreateGaps(true);
		bearbeitenTabelle.setAutoCreateContainerGaps(true);
		
		bearbeitenTabelle.setVerticalGroup(bearbeitenTabelle.createSequentialGroup().
				addComponent(scrollPane).
				addComponent(panelButton)
		);

		bearbeitenTabelle.setHorizontalGroup(bearbeitenTabelle.createParallelGroup().
				addComponent(scrollPane).
				addComponent(panelButton)
		);		

		panelButtonAnordnen();
	}

	private void panelButtonAnordnen(){
		
		panelButton.setLayout(new FlowLayout());
		panelButton.add(buttonBearbeiten);
		panelButton.add(buttonLoeschen);
		panelButton.add(buttonAbbrechen);
		
	}

	private void ereignissensorenAnmeldung() {
		
		buttonBearbeiten.addActionListener(this);
		buttonLoeschen.addActionListener(this);
		buttonAbbrechen.addActionListener(this);
	}
	
	private void setzeTableModel() {
		/*
		 * Jenachdem welcher modus übergeben wurde, wird das
		 * jeweilige tablemodel gesetzt!
		 * 1=>Pflanze;
		 * 2=>Duenger;
		 * 3=>Aussaat
		 */
		
		switch(modus){
		
		case 1: 
			tabelle.setModel(new PflanzeTableModel());
			setTitle("Pflanze Bearbeiten");
			break;
		case 2:
			tabelle.setModel(new DuengerTableModel());
			setTitle("Duenger Bearbeiten");
			break;
		case 3:
			tabelle.setModel(new AussaatTableModel());
			setTitle("Aussaat Bearbeiten");
			break;
		}	
	}

	private boolean doHohleAusgewaehlteZeile() {
		/*
		 * die jeweilige ausgewählte Zeile wird gehohlt
		 */
		int ausgwZeile = tabelle.getSelectedRow();
		
		try{
			switch(modus){
			
			case 1:	//Pflanze
					ausgewaehlteZeile.add((String) tabelle.getModel().getValueAt(ausgwZeile, 1)); // sorte
					ausgewaehlteZeile.add((String) tabelle.getModel().getValueAt(ausgwZeile, 2)); // art
					ausgewaehlteZeile.add((String) tabelle.getModel().getValueAt(ausgwZeile, 3)); // herkunft
					ausgewaehlteZeile.add((String) tabelle.getModel().getValueAt(ausgwZeile, 4)); // farbe
					ausgewaehlteZeile.add(((Integer) tabelle.getModel().getValueAt(ausgwZeile, 5)).toString()); // reifezeit
					ausgewaehlteZeile.add(((Integer) tabelle.getModel().getValueAt(ausgwZeile, 6)).toString()); // schaerfegrad
					ausgewaehlteZeile.add((String) tabelle.getModel().getValueAt(ausgwZeile, 7));// ertrag
					break;
			case 2: // Dünger
					ausgewaehlteZeile.add((String) tabelle.getModel().getValueAt(ausgwZeile, 1));//duengerMarke
					ausgewaehlteZeile.add((String) tabelle.getModel().getValueAt(ausgwZeile, 2));//kalium
					ausgewaehlteZeile.add((String) tabelle.getModel().getValueAt(ausgwZeile, 3));//magnesium
					ausgewaehlteZeile.add((String) tabelle.getModel().getValueAt(ausgwZeile, 4));//phosphat
					ausgewaehlteZeile.add((String) tabelle.getModel().getValueAt(ausgwZeile, 5));//stickstoff
				break;
			case 3://Aussaat
					ausgewaehlteZeile.add(((Integer) tabelle.getModel().getValueAt(ausgwZeile, 0)).toString()); // aussaatID	
					ausgewaehlteZeile.add((String) tabelle.getModel().getValueAt(ausgwZeile, 1)); // aussaatDatum
					ausgewaehlteZeile.add((String) tabelle.getModel().getValueAt(ausgwZeile, 2)); // pflanzOrt
					ausgewaehlteZeile.add((String) tabelle.getModel().getValueAt(ausgwZeile, 3)); // duengerMenge
					ausgewaehlteZeile.add((String) tabelle.getModel().getValueAt(ausgwZeile, 4));	// sorte
					ausgewaehlteZeile.add((String) tabelle.getModel().getValueAt(ausgwZeile, 5)); // duengerMarke
				break;
			}
		
		}catch(IllegalArgumentException ia){
			
			System.out.println("Bitte eine Zeile auswählen");
			JOptionPane.showMessageDialog(null,"Bitte eine Zeile auswählen","Fehler",JOptionPane.ERROR_MESSAGE);
			return false;
			
		}
		
		return true;
		
	}
	
	private void warnungLoescheAussaat() {

		int selected = JOptionPane.showOptionDialog(null, "Wenn Sie diese Aussaat löschen, werden alle dazugehörigen " +
						"Fortschritte (Wachstum,Bewässerung sowie Ernten) auch gelöscht"
						, "ACHTUNG!", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[1]);
		
		switch(selected){
		
		case 0: // Ja
			Aussaat augewaehlteAussaat = hohleAusgewaehlteAussaat();
			loescheFortschritte(augewaehlteAussaat);
			loescheAussaat(augewaehlteAussaat);
			loeschenBestaetigen();
			break;
		case 1: // Abbrechen
			System.out.println("Abbruch Aussaat löschen");
			break;
		}
	}

	private Aussaat hohleAusgewaehlteAussaat() {
		
		int aussaatID = Integer.parseInt(ausgewaehlteZeile.get(0));
		EntityManagerFactory factory;
		factory = Persistence.createEntityManagerFactory("chilidatenbank");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		
		Query q = em.createQuery("SELECT a FROM Aussaat a WHERE a.aussaatID =:ID");
		  q.setParameter("ID",aussaatID);
		 
		Aussaat aussaat = (Aussaat) q.getSingleResult();
		
		stringBuilder.append("Es wurde die Aussaat mit der ID = "+aussaatID+" gelöscht");
		em.close();
		return aussaat;
	}

	private void loescheFortschritte(Aussaat aussaat) {
		/*
		 * Um die Aussaat loeschen zu können müssen vorher Tabellen gelöscht werden
		 * die als Fremdschlüssel die AussaatID beinhalten.
		 * Es wird also geprüft ob es für die Aussaat einen Wachstum , Bewässerung oder Ernte gibt
		 * falls dies der Fall ist werden diese bevor die Aussaat gelöscht wird gelöscht.
		 */
		int wachstumID = 0;
		int bewaesserungID = 0;

		EntityManagerFactory factory;
		factory = Persistence.createEntityManagerFactory("chilidatenbank");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		Query q;

		Wachstum wachstum = aussaat.getWachstum();
		Bewaesserung bewaesserung = aussaat.getBewaesserung();
		List<Ernte> erntenZumLoeschen = aussaat.getErnte();
		
		/*
		 * Da eine Aussaat mehrere Ernten haben kann
		 * müssen diese alle gelöscht werden
		 */
		loescheErnten(erntenZumLoeschen);
		
		 
		 /* Wenn Wachstum vorhanden => Löschen
		  * Falls nicht vorhanden wird bei der zuweisung eine Exception geworfen
		  * und gefangen!
		  * Gleicher abblauf bei bewaesserung
		  */
		 try{
			 wachstumID = wachstum.getWachstumID();
			 q = em.createQuery("DELETE FROM Wachstum w WHERE w.wachstumID =:ID");
		 	 	q.setParameter("ID", wachstumID);
		 	 	q.executeUpdate();	 
		 	 
		 }catch(NullPointerException e){
			 System.out.println("Kein Wachstum vorhanden");
		 }
		 try{
			 bewaesserungID = bewaesserung.getBewaesserungID();
			 q = em.createQuery("DELETE FROM Bewaesserung b WHERE b.bewaesserungID =:ID");
			 	q.setParameter("ID",bewaesserungID);
			 	q.executeUpdate();
		 	 
		 }catch(NullPointerException e){
			 System.out.println("Keine Bewässerung vorhanden");
		 }		
		 
		em.getTransaction().commit();
		em.clear();
		em.close();
	}

	private void loescheAussaat(Aussaat aussaat) {
		
		EntityManagerFactory factory;
		factory = Persistence.createEntityManagerFactory("chilidatenbank");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		
		Query q = em.createQuery("DELETE FROM Aussaat a WHERE a.aussaatID =:ID");
		 	q.setParameter("ID", aussaat.getAussaatID());
		 	q.executeUpdate();
		 	
		/*
		 *  Zum schluss muss die Aussaat aus den Listen
		 *  der Tabellen Pflanze und Duenger gelöscht werden,
		 *  damit es wenn z.B eine Pflanze gelöscht wird nicht zu fehlern kommt
		 *  weil es noch ein verweis auf eine nicht vorhandene Aussaat gibt.
		 *  
		 *  Dies muss man aber nicht für alle Tabellen tun da wir nicht direkt mit 
		 *  diesen arbeiten, und die leeren verweise in den Listen nach neustart
		 *  des Programms geelöscht sind.
		 *  
		 */
		 	
		Pflanze pflanze = aussaat.getPflanze();
		pflanze.getAussaat().remove(aussaat);
		
		Duenger duenger = aussaat.getDuenger();
		duenger.getAussaat().remove(aussaat);
	  
		em.getTransaction().commit();
		em.clear();
		em.close();
	}

	private void loescheErnten(List<Ernte> erntenZumLoeschen) {
		
		if(erntenZumLoeschen.isEmpty()){
			
			System.out.println("Keine Ernte vorhanden");
		}else{
			
			for(int i=0;i<erntenZumLoeschen.size();i++){
				/*
				 * Hier wird kein zurücksetzen wie in loescheAusaaten() benötigt,
				 * da wir in der methode loescheErnte() die aussaaten nicht "per hand"
				 * aus der ernte entfernen ( liste ) wird die ernteZumLoeschen Liste nicht 
				 * nach jedem Schritt kleiner.
				 */
				
				Ernte ernte = erntenZumLoeschen.get(i);
				loescheErnte(ernte);
			}
		}	
	}

	private void loescheErnte(Ernte ernte) {

		EntityManagerFactory factory;
		factory = Persistence.createEntityManagerFactory("chilidatenbank");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		
		System.out.println(ernte.getErnteID());
		
		Query q = em.createQuery("DELETE FROM Ernte e WHERE e.ernteID =:ID");	
				  q.setParameter("ID", ernte.getErnteID());
				  q.executeUpdate();
		
		em.getTransaction().commit();
		em.clear();
		em.close();
				  			  
	}

	private void warnungLoescheDuenger() {

		int selected = JOptionPane.showOptionDialog(null, "Wenn Sie diesen Dünger löschen, werden ALLE aktuellen " +
					  "Aussaaten(inklusive vorhandenen Fortschritten) die diese Dünger nutzen auch gelöscht!"
					  , "ACHTUNG!", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[1]);
		
		switch(selected){
		
		case 0: // Ja
			loescheAusgewaehltenDuenger();
			break;
		case 1://Abbrechen
			System.out.println("Abbruch Dünger löschen");
			break;
		}
	}

	private void loescheAusgewaehltenDuenger() {
		
		EntityManagerFactory factory;
		factory = Persistence.createEntityManagerFactory("chilidatenbank");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		
		findeAussaatDuenger();
		
		Query q = em.createQuery("DELETE FROM Duenger d WHERE d.duengerMarke = :name");
			    q.setParameter("name", ausgewaehlteZeile.get(0)).executeUpdate();
		
		em.getTransaction().commit();
		em.close();
		
		stringBuilder.append("Es wurde der Dünger mit der Marke: ").append(ausgewaehlteZeile.get(0)).append(" gelöscht");
		loeschenBestaetigen();
		
	}

	private void findeAussaatDuenger() {
		/*
		 *  Es werden alle Aussaaten gesucht die den zu löschenden Dünger beinhalten!
		 *  Anschließend werden diese gelöscht
		 */
		
		EntityManagerFactory factory;
		factory = Persistence.createEntityManagerFactory("chilidatenbank");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		
		Query q = em.createQuery("SELECT d FROM Duenger d WHERE d.duengerMarke = :name");
		  q.setParameter("name", ausgewaehlteZeile.get(0));  

		Duenger duenger  = (Duenger) q.getSingleResult();			
		List<Aussaat> aussaatZumLoeschen = duenger.getAussaat();	

		loescheAussaaten(aussaatZumLoeschen);
		
		
		em.persist(duenger);
		em.getTransaction().commit();
		em.close();
		
	}

	private void loescheAussaaten(List<Aussaat> aussaatZumLoeschen) {
		/*
		 *  Mit dieser Methode können mehrere AussaateN gelöscht werden!
		 */
		System.out.println("Listengröße1: "+aussaatZumLoeschen.size());
		stringBuilder.append("Es wurden ").append(aussaatZumLoeschen.size()).append(" Aussaaten mit den folgenden ID/s gelöscht: \n");
		System.out.println("GRöße vom Liste:"+aussaatZumLoeschen.size());
		
		if(aussaatZumLoeschen.isEmpty()){
			
			stringBuilder.append("'Keine Aussaaten gefunden die das zu löschende Element verwenden'\n");
			
		}else{
			/*
			 * Wenn Aussaat/en vorhanden dan wird die Liste  durchsucht und Aussaat/en  gelöscht!
			 */
			
			for(int i=0;i<=aussaatZumLoeschen.size();i++){
				
				System.out.println("Listengröße: "+aussaatZumLoeschen.size());
				Aussaat aussaat = aussaatZumLoeschen.get(0);// Da die liste jeden durchlauf kleiner wird hohlen wir immer die stelle 0
				i=0; // zurücksetzen des zählers da sonst nicht alle Aussaaten gelöscht werden
			
				stringBuilder.append("ID: ").append(aussaat.getAussaatID()).append(" ");
				loescheFortschritte(aussaat);
				loescheAussaat(aussaat);
					
			}
			stringBuilder.append("\n");
		}		
	}

	private void warnungLoeschePflanze() {
		
		Object[] options = {"Ja!","Abbrechen!"};
		int selected = JOptionPane.showOptionDialog(null, "Wenn Sie diese Pflanze löschen, werden ALLE aktuellen" +
					 " Aussaaten(inklusive vorhandenen Fortschritten) die diese Pflanze enthalten auch gelöscht!"
					 , "ACHTUNG!", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[1]);
		
		switch (selected){
	
		case 0://Ja 
			loescheAusgewaehltePflanze();		
			break;
	
		case 1://Abbrechen
			System.out.println("Abbruch Pflanze löschen");
		break;
		}
	}

	private void loescheAusgewaehltePflanze() {
		
		EntityManagerFactory factory;
		factory = Persistence.createEntityManagerFactory("chilidatenbank");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		
		//Erst müssen die Aussaaten gelöscht werden die die zu löschende Pflanze
		//beinhalten
		findeAussaatPflanze();
		
		Query q = em.createQuery("DELETE FROM Pflanze p WHERE p.sorte = :name");
			    q.setParameter("name", ausgewaehlteZeile.get(0)).executeUpdate();
		
		em.getTransaction().commit();
		em.close();
		
		stringBuilder.append("Und die Pflanze mit der Sorte: ").append(ausgewaehlteZeile.get(0));
		loeschenBestaetigen();
		
		
	}
	
	private void findeAussaatPflanze() {
		/*
		 * Alle Aussaaten die die zu löschende Pflanze beinhalten werden gesucht und gelöscht!
		 */
		EntityManagerFactory factory;
		factory = Persistence.createEntityManagerFactory("chilidatenbank");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		
		Query q = em.createQuery("SELECT p FROM Pflanze p WHERE p.sorte = :name");
		  q.setParameter("name", ausgewaehlteZeile.get(0));
		  
		Pflanze p  = (Pflanze) q.getSingleResult();			
		List<Aussaat> aussaatZumLoeschen = p.getAussaat();	
		loescheAussaaten(aussaatZumLoeschen);
		
		em.persist(p);
		em.getTransaction().commit();
		em.close();
		
	}

	private void loeschenBestaetigen() {
		
		// Bestätigung wird ausgegeben und StringBuilder resetet
		Object[] option = {"Ok"};
		
		JOptionPane.showOptionDialog(null,stringBuilder.toString(), "Löschen Erfolgreich", JOptionPane.YES_OPTION,
				   JOptionPane.OK_OPTION, null , option, null);
		stringBuilder.setLength(0);
		dispose();
		
	}

}